
set +x
EnvName={{.EnvName}}
DeployHost={{.DockerLabel}}
Git={{.Git}}

BackendServiceName={{.ServiceName}}
CeleryBeatServiceName={{.CeleryBeatServiceName}}
CeleryWorkerServiceName={{.CeleryWorkerServiceName}}

BackendMediaVolume={{.BackendMediaVolume}} # /mnt/gv1/karbon_share
BackendStaticVolume={{.BackendStaticVolume}}

DockerNetwork={{.DockerNetwork}}
DockerRepository={{.DockerRepository}}
DockerManagerHost={{.DockerManagerHost}}
DockerManagerUser={{.DockerManagerUser}}
DockerManagerPort={{.DockerManagerPort}}
DockerReserveMemory=3GB

set -eu; set -o pipefail
UseConfigManage=$use_config_manage
# backend public media and private media folder which are shared between all instances
BackendPublicMediaVolume=$BackendMediaVolume/public_media
BackendPrivateMediaVolume=$BackendMediaVolume/private_media

BuildRootDir=/opt/karbon_build
ProjectName=$(basename "$Git" | cut -d . -f 1)
BuildWorkDir="$BuildRootDir/$EnvName/${ProjectName}_build"


DockerBuildDir=$BuildWorkDir/docker_tmp_dir
BackendRunRoot=/opt/karbon_app
# folders in docker container
BackendStaticRoot=$BackendRunRoot/backend_collectstatic
BackendPublicMediaRoot=$BackendRunRoot/public_media
BackendPrivateMediaRoot=$BackendRunRoot/private_media

BranchName="$Version"

ConfigFileName=local_settings.py
OldFileKeep=7
ConfigBackupDir=$BuildWorkDir/backend_config
ConfigFileDst=$BuildWorkDir/$ProjectName/project/settings

KarbonKeys=$BuildRootDir/backend_common/karbon_keys
KarbonDataImport=$BuildRootDir/backend_common/karbon_data_import
DockerImageName=${EnvName}_${ProjectName}:$BranchName

echo "=== going to deploy version: $BranchName"

LocalDir=$(pwd)

if [[ ! -d "$ConfigBackupDir" ]]; then mkdir -p "$ConfigBackupDir" ; fi
if [[ ! -d "$DockerBuildDir" ]]; then mkdir -p "$DockerBuildDir" ; fi
cd "$BuildWorkDir"
if [[ ! -d "$ProjectName" ]]; then
  git clone "$Git"
fi

cd "$ProjectName"
git checkout -f
git fetch
# if branch name starts with 'v', means it's a tag
if [[ "${BranchName:0:1}" == "v" ]]; then
  git checkout "$BranchName"
else
  git checkout "$BranchName"
  git reset --hard "origin/$BranchName"
fi

if [[ "$UseConfigManage" == "yes" ]]; then
  # get config file from config file management system
  config_result=$(curl -s -w "%{http_code}" \
        -d '{"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxIiwiaXNzIjoiay1kZXZlbG9wIn0.Fl1dr2lVHAvL09zrWY6Kx_bXGGc76ma8_PCZ6tYemhs", "instanceName": "docker_config_template"}' \
          -o "$LocalDir/${ConfigFileName}_tmp" -X POST https://devops.prewater.com/api/getconfig \
      )
  if [[ "$config_result" -eq "200" ]]; then
    cp "$LocalDir/${ConfigFileName}_tmp" "$LocalDir/${ConfigFileName}"
    # replace 'docker_config_template' with EnvName
    sed -i 's/docker_config_template/'"$EnvName"'/g' "$LocalDir/${ConfigFileName}"
  else
    echo "==== Failed to get ${ConfigFileName} from ConnfigFileManageSys, use old one"
  fi
fi
cp "$LocalDir/${ConfigFileName}" "$ConfigFileDst/"

# backup config file
if [[ -f "$ConfigBackupDir/${ConfigFileName}" ]]; then
  mv "$ConfigBackupDir"/${ConfigFileName} "$ConfigBackupDir/${ConfigFileName}_$(date +%Y%m%d%M%S)"
  find "$ConfigBackupDir"/ -maxdepth 1 ! -mtime $OldFileKeep -name "${ConfigFileName}"* -delete
fi
cp "$LocalDir/${ConfigFileName}" "$ConfigBackupDir/"

# copy files into docker build tmp dir
rm -rf "${DockerBuildDir:?}"/*  # don't use double quote, if use quote will prevent * from be extend by out shell
cp -a "$BuildWorkDir/$ProjectName" "$DockerBuildDir/"
cp -a "$KarbonKeys" "$DockerBuildDir/"
cp -a "$KarbonDataImport" "$DockerBuildDir/"

# delete old docker image
# set +o pipefail; sudo docker image ls | grep "${DockerImageName%%:*}" |sort  | awk '{print $1":"$2}' | xargs -r sudo docker image rm
# set -o pipefail

sudo docker build --no-cache --rm --force-rm -t "$DockerImageName" -f- "$DockerBuildDir" <<EOF
FROM 10.110.0.11:5000/kpython36:latest

COPY ./$ProjectName $BackendRunRoot/$ProjectName/
COPY ./$(basename $KarbonKeys) $BackendRunRoot/karbon_files/$(basename $KarbonKeys)/
COPY ./$(basename $KarbonDataImport) $BackendRunRoot/karbon_files/$(basename $KarbonDataImport)/
WORKDIR $BackendRunRoot/$ProjectName
RUN python3.6 -m pip install -r $BackendRunRoot/$ProjectName/requirements.txt
EXPOSE 80
CMD ["gunicorn", "-w", "2", "--forwarded-allow-ips=*", "--bind=0.0.0.0:80", "project.wsgi:application", "--chdir=$BackendRunRoot/$ProjectName",  "-p", "/tmp/gunicorn.pid"]
EOF

# rm old django services
echo "try to remove old backend service:$BackendServiceName"
set +e
rmResult=$(ssh -p "$DockerManagerPort" ${DockerManagerUser}@${DockerManagerHost} sudo docker service rm $BackendServiceName 2>&1)
if ! [[ "$rmResult" == "$BackendServiceName" ]]; then
  # not such service, it's ok
  if ! echo "$rmResult" | grep -i "such service: $BackendServiceName"; then
    echo "=== something wrong when rm docker service of django"
    exit 1
  fi
fi
# remove celery beat
echo "=== try to remove old celery beat service: $CeleryBeatServiceName"
rmResult=$(ssh -p "$DockerManagerPort" ${DockerManagerUser}@${DockerManagerHost} sudo docker service rm $CeleryBeatServiceName 2>&1)
if ! [[ "$rmResult" == "$CeleryBeatServiceName" ]]; then
  # not such service, it's ok
  if ! echo "$rmResult" | grep -i "such service: $CeleryBeatServiceName"; then
    echo "=== something wrong when rm docker service of celery beat"
    exit 1
  fi
fi
# remove celery worker
echo "=== try to remove old celery worker service: $CeleryWorkerServiceName"
rmResult=$(ssh -p "$DockerManagerPort" ${DockerManagerUser}@${DockerManagerHost} sudo docker service rm $CeleryWorkerServiceName 2>&1)
if ! [[ "$rmResult" == "$CeleryWorkerServiceName" ]]; then
  # not such service, it's ok
  if ! echo "$rmResult" | grep -i "such service: $CeleryWorkerServiceName"; then
    echo "=== something wrong when rm docker service of celery worker"
    exit 1
  fi
fi
set -e

# remove backend static file volume in local host (which is using glusterfs)
echo "=== try to remove backend static collected folder"
if [[ ${#BackendStaticVolume} -gt 20 ]]; then
    sudo rm -rf ${BackendStaticVolume}/*
else
    echo "=== the length little then 20 when deleting ${BackendStaticVolume}"
    exit 1
fi

# run python manage.py migrate, update_message_notification in docker
# log-driver to let docker not to use rsyslog, which is set in daemon.conf
echo "=== run backend image once to do db migrate etc."
sudo docker run -a stdout -a stderr --log-driver syslog --rm -v $BackendStaticVolume:$BackendStaticRoot \
--network $DockerNetwork  "$DockerImageName" bash -c "\
	python3.6 manage.py collectstatic && \
  python3.6 manage.py migrate && \
  python3.6 manage.py compile_db && \
  python3.6 manage.py update_notification_template"

# push to image to the registry
echo "tag docker image and push to customer registry"
sudo docker tag "$DockerImageName" "$DockerRepository/$DockerImageName"
sudo docker push 10.110.0.11:5000/"$DockerImageName"
sudo docker image rm "$DockerImageName"

# deploy backend, celery beat and worker
if [[ $DeployHost == "" ]]; then
  ssh -p "$DockerManagerPort" $DockerManagerUser@$DockerManagerHost sudo docker service create \
    --reserve-memory=$DockerReserveMemory \
    --name $BackendServiceName\
    --network $DockerNetwork \
    --mount type=bind,source=$BackendStaticVolume,destination=$BackendStaticRoot \
    --mount type=bind,source=$BackendPublicMediaVolume,destination=$BackendPublicMediaRoot \
    --mount type=bind,source=$BackendPrivateMediaVolume,destination=$BackendPrivateMediaRoot \
    "$DockerRepository/$DockerImageName"
else
  ssh -p "$DockerManagerPort" $DockerManagerUser@$DockerManagerHost sudo docker service create \
    --reserve-memory=$DockerReserveMemory \
    --name $BackendServiceName\
    --network $DockerNetwork \
    --mount type=bind,source=$BackendStaticVolume,destination=$BackendStaticRoot \
    --mount type=bind,source=$BackendPublicMediaVolume,destination=$BackendPublicMediaRoot \
    --mount type=bind,source=$BackendPrivateMediaVolume,destination=$BackendPrivateMediaRoot \
    --constraint node.labels.khost==$DeployHost \
    "$DockerRepository/$DockerImageName"
fi

if [[ $DeployHost == "" ]]; then
  ssh -p "$DockerManagerPort" $DockerManagerUser@$DockerManagerHost sudo docker service create \
    --reserve-memory=$DockerReserveMemory \
    --name $CeleryBeatServiceName \
    --network $DockerNetwork \
    "$DockerRepository/$DockerImageName" \
    celery -A project.celery_tasks.celery beat -l debug --scheduler django_celery_beat.schedulers:DatabaseScheduler
else
  ssh -p "$DockerManagerPort" $DockerManagerUser@$DockerManagerHost sudo docker service create \
    --reserve-memory=$DockerReserveMemory \
    --name $CeleryBeatServiceName \
    --network $DockerNetwork \
    --constraint node.labels.khost==$DeployHost\
    "$DockerRepository/$DockerImageName" \
    celery -A project.celery_tasks.celery beat -l debug --scheduler django_celery_beat.schedulers:DatabaseScheduler
fi

if [[ $DeployHost == "" ]]; then
  ssh -p "$DockerManagerPort" $DockerManagerUser@$DockerManagerHost sudo docker service create \
    --reserve-memory=$DockerReserveMemory \
    --name $CeleryWorkerServiceName \
    --network $DockerNetwork \
    "$DockerRepository/$DockerImageName" \
    celery -A project.celery_tasks.celery worker -l info -c 2
else
  ssh -p "$DockerManagerPort" $DockerManagerUser@$DockerManagerHost sudo docker service create \
    --reserve-memory=$DockerReserveMemory \
    --name $CeleryWorkerServiceName \
    --network $DockerNetwork \
    --constraint node.labels.khost==$DeployHost\
    "$DockerRepository/$DockerImageName" \
    celery -A project.celery_tasks.celery worker -l info -c 2
fi

